"""截图置顶显示模块"""

import sys
import tkinter as tk
from tkinter import filedialog
from tkinter import messagebox

from PIL import Image, ImageTk

try:
    from PIL import ImageGrab
except ImportError:
    ImageGrab = None


class ScreenshotOverlay:
    """截图置顶显示窗口类"""

    # 用于跟踪当前打开的overlay窗口实例
    _current_overlay = None

    def __init__(self, image, position):
        """
        初始化置顶显示窗口

        Args:
            image (PIL.Image): 要显示的图像
            position (tuple): 显示位置 (left, top)
        """
        self.tip_window = None
        self.image = image
        self.position = position
        self.root = None
        self.photo = None
        self.start_x = None
        self.start_y = None
        self.canvas = None
        self.rect = None
        self.start_x_draw = None
        self.start_y_draw = None
        self.current_rect = None
        self.drawing = False
        self.menu = None
        self.display_image = image  # 用于旋转操作的图像
        self.rectangles = []  # 存储所有绘制的矩形
        self.deleted_rectangles = []  # 存储被删除的矩形（用于撤销）

    def show_overlay(self):
        """
        在原始截图位置显示置顶图像（非阻塞方式）
        """
        # 关闭任何已存在的overlay窗口
        if ScreenshotOverlay._current_overlay:
            ScreenshotOverlay._current_overlay.close_overlay()

        # 将当前实例设置为_current_overlay
        ScreenshotOverlay._current_overlay = self

        try:
            # 创建顶层窗口
            self.root = tk.Toplevel()
            self.root.title("截图预览")

            # 移除窗口装饰（标题栏、边框等）
            if sys.platform == "win32":
                self.root.overrideredirect(True)
            else:
                self.root.attributes('-type', 'splash')

            # 获取图像尺寸
            img_width, img_height = self.image.size

            # 限制最大窗口尺寸，防止图像太大时超出屏幕
            max_width = min(img_width, self.root.winfo_screenwidth() - 100)
            max_height = min(img_height, self.root.winfo_screenheight() - 150)  # 为提示文本和边框留出空间

            # 如果图像尺寸超过限制，则按比例缩放
            self.display_image = self.image
            if img_width > max_width or img_height > max_height:
                # 计算缩放比例
                scale = min(max_width / img_width, max_height / img_height)
                new_width = int(img_width * scale)
                new_height = int(img_height * scale)

                # 缩放图像
                self.display_image = self.image.resize((new_width, new_height), Image.LANCZOS)
                img_width, img_height = new_width, new_height

            # 设置窗口位置和尺寸（包含图像、黑边和提示文本的空间）
            left, top = self.position
            # 窗口宽度至少要能容纳提示文本，同时考虑左右边距
            window_width = img_width + 2  # 图像宽度+边框
            # 窗口高度包括图像高度和上下边距
            window_height = img_height + 2  # 图像高度 + 上下边距(各1px)
            self.root.geometry(f"{window_width}x{window_height}+{left}+{top}")

            # 设置窗口置顶
            self.root.attributes('-topmost', True)

            # 设置背景为黑色
            self.root.configure(bg='black')

            # 转换图像格式以便在tkinter中显示
            # 注意：必须在创建窗口后创建PhotoImage对象
            self.photo = ImageTk.PhotoImage(self.display_image)

            # 创建Canvas用于显示图像和绘制
            self.canvas = tk.Canvas(self.root, width=img_width, height=img_height, bg='black', highlightthickness=0)
            self.canvas.pack(pady=(1, 1), padx=1)  # 上下各1像素边距，左右各1像素边距

            # 在Canvas上显示图像
            self.canvas.create_image(0, 0, anchor=tk.NW, image=self.photo)

            # 创建独立的提示窗口
            self.tip_window = tk.Toplevel()
            self.tip_window.overrideredirect(True)
            self.tip_window.attributes('-topmost', True)
            self.tip_window.configure(bg='#333333')  # 深灰色背景
            self.tip_window.withdraw()  # 默认隐藏

            # 创建提示文本标签，使用更小的字体和更紧凑的边距
            tip_label = tk.Label(
                self.tip_window,
                text="左键拖拽移动 | 右键菜单 | Ctrl+左键框选 | Delete撤销",
                fg="white",
                bg="#333333",
                font=("微软雅黑", 8),
                padx=3,
                pady=2
            )
            tip_label.pack()

            # 创建右键菜单
            self.menu = tk.Menu(self.root, tearoff=0)
            self.menu.add_command(label="保存", command=self.save_image)
            self.menu.add_command(label="复制", command=self.copy_to_clipboard)
            self.menu.add_command(label="旋转90度", command=self.rotate_image)
            self.menu.add_separator()
            self.menu.add_command(label="关闭", command=self.close_overlay)

            # 绑定鼠标进入和离开事件来显示/隐藏提示窗口
            self.canvas.bind("<Enter>", self.show_tip)
            self.canvas.bind("<Leave>", self.hide_tip)

            # 绑定鼠标移动事件来更新提示窗口位置
            self.canvas.bind("<Motion>", self.move_tip)

            # 绑定鼠标事件以支持窗口拖动
            self.canvas.bind("<Button-1>", self.start_move)  # 左键按下开始拖动
            self.canvas.bind("<B1-Motion>", self.do_move)  # 左键拖动进行移动
            self.canvas.bind("<ButtonRelease-1>", self.stop_move)  # 左键释放停止拖动

            # 绑定绘制事件 (Ctrl+左键)
            self.canvas.bind("<Control-Button-1>", self.start_draw)
            self.canvas.bind("<Control-B1-Motion>", self.draw_rectangle)
            self.canvas.bind("<Control-ButtonRelease-1>", self.stop_draw)

            # 绑定撤销操作 (Delete键)
            self.root.bind("<Delete>", self.undo_last_rectangle)

            # 绑定右键菜单事件
            self.canvas.bind("<Button-3>", self.show_context_menu)  # 右键显示菜单
            self.root.bind("<Escape>", self.close_overlay)  # ESC键关闭

        except Exception as e:
            print(f"显示截图置顶窗口时出错: {e}")
            if self.root:
                self.root.destroy()

    def start_move(self, event):
        """
        开始移动窗口

        Args:
            event: 鼠标事件
        """
        # 记录鼠标按下时的初始位置
        self.start_x = event.x
        self.start_y = event.y

        # 在拖动开始时隐藏提示窗口
        self.hide_tip()

    def do_move(self, event):
        """
        执行窗口移动

        Args:
            event: 鼠标事件
        """
        if self.start_x is not None and self.start_y is not None:
            # 计算新位置
            x = self.root.winfo_x() + event.x - self.start_x
            y = self.root.winfo_y() + event.y - self.start_y

            # 移动窗口
            self.root.geometry(f"+{x}+{y}")

    def stop_move(self, event):
        """
        停止移动窗口

        Args:
            event: 鼠标事件
        """
        # 重置初始位置
        self.start_x = None
        self.start_y = None

    def start_draw(self, event):
        """
        开始绘制矩形框

        Args:
            event: 鼠标事件
        """
        self.drawing = True
        self.start_x_draw = event.x
        self.start_y_draw = event.y

        # 创建新的矩形框
        self.current_rect = self.canvas.create_rectangle(
            self.start_x_draw, self.start_y_draw,
            self.start_x_draw, self.start_y_draw,
            outline='red', width=2
        )

    def draw_rectangle(self, event):
        """
        绘制矩形框过程

        Args:
            event: 鼠标事件
        """
        if self.drawing and self.current_rect:
            # 更新矩形框的坐标
            self.canvas.coords(
                self.current_rect,
                self.start_x_draw, self.start_y_draw,
                event.x, event.y
            )

    def stop_draw(self, event):
        """
        停止绘制矩形框

        Args:
            event: 鼠标事件
        """
        if self.drawing and self.current_rect:
            # 将当前矩形添加到矩形列表中
            self.rectangles.append(self.current_rect)
            # 清空删除历史（新的绘制操作会使撤销历史失效）
            self.deleted_rectangles.clear()
            self.drawing = False
            self.current_rect = None

    def undo_last_rectangle(self, event=None):
        """
        撤销最后一个绘制的矩形框

        Args:
            event: 事件对象
        """
        if self.rectangles:
            # 从画布上删除最后一个矩形
            last_rect = self.rectangles.pop()
            self.deleted_rectangles.append(last_rect)
            self.canvas.delete(last_rect)

    def show_context_menu(self, event):
        """
        显示右键上下文菜单

        Args:
            event: 鼠标事件
        """
        try:
            self.menu.tk_popup(event.x_root, event.y_root)
        finally:
            self.menu.grab_release()

    def save_image(self):
        """
        保存图像到文件（包含绘制的矩形框）
        """
        try:
            file_path = filedialog.asksaveasfilename(
                defaultextension=".png",
                filetypes=[
                    ("PNG files", "*.png"),
                    ("JPEG files", "*.jpg"),
                    ("BMP files", "*.bmp"),
                    ("All files", "*.*")
                ]
            )
            if file_path:
                # 创建一个副本用于保存，避免修改原始图像
                image_to_save = self.image.copy()

                # 如果有绘制的矩形框，则在图像上绘制它们
                if self.rectangles:
                    from PIL import ImageDraw
                    draw = ImageDraw.Draw(image_to_save)

                    # 获取画布上所有矩形的坐标，并转换为图像坐标
                    for rect in self.rectangles:
                        coords = self.canvas.coords(rect)
                        if coords and len(coords) == 4:
                            # 需要将Canvas坐标转换为原始图像坐标
                            # 首先获取Canvas的图像尺寸和原始图像尺寸
                            canvas_width = self.canvas.winfo_width()
                            canvas_height = self.canvas.winfo_height()
                            image_width, image_height = self.image.size

                            # 计算坐标缩放比例
                            scale_x = image_width / canvas_width
                            scale_y = image_height / canvas_height

                            # 转换坐标
                            x1, y1, x2, y2 = coords
                            x1_scaled = int(x1 * scale_x)
                            y1_scaled = int(y1 * scale_y)
                            x2_scaled = int(x2 * scale_x)
                            y2_scaled = int(y2 * scale_y)

                            # 在图像上绘制红色矩形框
                            draw.rectangle([x1_scaled, y1_scaled, x2_scaled, y2_scaled],
                                           outline='red', width=2)

                # 保存图像
                image_to_save.save(file_path)
                messagebox.showinfo("保存成功", f"图像已保存到: {file_path}")
        except Exception as e:
            messagebox.showerror("保存失败", f"保存图像时出错: {e}")

    def copy_to_clipboard(self):
        """
        将当前图像复制到系统剪切板（仅支持Windows）
        """
        try:
            # 仅在Windows上使用win32clipboard
            if sys.platform == "win32":
                # 显式导入 win32clipboard 并检查是否成功
                import win32clipboard
                import io

                output = io.BytesIO()
                self.image.save(output, 'BMP')
                data = output.getvalue()[14:]  # BMP header is 14 bytes
                output.close()

                win32clipboard.OpenClipboard()
                win32clipboard.EmptyClipboard()
                win32clipboard.SetClipboardData(win32clipboard.CF_DIB, data)
                win32clipboard.CloseClipboard()

                # 创建非阻塞提示窗口
                self.show_non_blocking_message("成功", "图像已复制到剪切板")
            else:
                # 其他平台暂不支持图像复制
                messagebox.showwarning("提示", "当前操作系统不支持直接复制图像到剪贴板")
        except ImportError as e:
            # 如果win32clipboard不可用，提示用户安装
            messagebox.showerror("错误", f"缺少必要的模块: {e}\n请运行 'pip install pywin32' 安装")
        except Exception as e:
            messagebox.showerror("复制失败", f"复制到剪切板时出错: {e}")

    def show_non_blocking_message(self, title, message):
        """
        显示非阻塞的提示消息，3秒后自动关闭，位于屏幕右下角，无边框、深色背景、半透明
        
        Args:
            title (str): 提示标题
            message (str): 提示内容
        """
        # 创建临时提示窗口
        tip_window = tk.Toplevel(self.root)
        tip_window.title(title)
        tip_window.geometry("150x40")  # 更小的尺寸
        tip_window.attributes('-topmost', True)  # 置顶显示
        tip_window.overrideredirect(True)  # 移除边框和标题栏
        tip_window.configure(bg='#111111')  # 深色背景（接近黑色）
        tip_window.attributes('-alpha', 0.8)  # 半透明效果

        # 添加提示标签
        label = tk.Label(
            tip_window,
            text=message,
            fg="white",
            bg="#111111",
            font=("微软雅黑", 8),
            padx=5,
            pady=5
        )
        label.pack(expand=True)

        # 定位到屏幕右下角
        tip_window.update_idletasks()  # 确保窗口尺寸已计算
        width = tip_window.winfo_width()
        height = tip_window.winfo_height()
        x = tip_window.winfo_screenwidth() - width - 20  # 距离右侧20像素
        y = tip_window.winfo_screenheight() - height - 20  # 距离底部20像素
        tip_window.geometry(f"{width}x{height}+{x}+{y}")

        # 设置3秒后自动关闭
        tip_window.after(3000, tip_window.destroy)

    def rotate_image(self):
        """
        将图像旋转90度
        """
        try:
            # 保存原始显示图像的尺寸
            original_width, original_height = self.display_image.size

            # 旋转图像
            self.display_image = self.display_image.rotate(-90, expand=True)
            self.image = self.image.rotate(-90, expand=True)

            # 更新显示
            self.photo = ImageTk.PhotoImage(self.display_image)

            # 更新画布尺寸
            new_img_width, new_img_height = self.display_image.size
            self.canvas.config(width=new_img_width, height=new_img_height)

            # 清除画布并重新显示图像
            self.canvas.delete("all")
            self.canvas.create_image(0, 0, anchor=tk.NW, image=self.photo)

            # 重新绘制所有矩形框，正确转换坐标
            new_rectangles = []
            for rect in self.rectangles:
                # 获取原始矩形坐标
                coords = self.canvas.coords(rect)
                if coords and len(coords) == 4:
                    x1, y1, x2, y2 = coords
                    # 90度旋转坐标转换 (逆时针)
                    # 原始点 (x, y) -> 旋转后点 (y, original_width - x)
                    new_x1 = y1
                    new_y1 = original_width - max(x1, x2)
                    new_x2 = y2
                    new_y2 = original_width - min(x1, x2)

                    # 确保坐标顺序正确 (左上到右下)
                    final_x1, final_x2 = min(new_x1, new_x2), max(new_x1, new_x2)
                    final_y1, final_y2 = min(new_y1, new_y2), max(new_y1, new_y2)

                    # 重新创建矩形
                    new_rect = self.canvas.create_rectangle(final_x1, final_y1, final_x2, final_y2, outline='red',
                                                            width=2)
                    new_rectangles.append(new_rect)
                else:
                    # 如果坐标无效，保留原始矩形
                    new_rectangles.append(rect)
            self.rectangles = new_rectangles

            # 调整窗口大小以适应旋转后的图像
            img_width, img_height = self.display_image.size
            window_width = img_width + 2
            window_height = img_height + 2
            x = self.root.winfo_x()
            y = self.root.winfo_y()
            self.root.geometry(f"{window_width}x{window_height}+{x}+{y}")

        except Exception as e:
            messagebox.showerror("旋转失败", f"旋转图像时出错: {e}")

    def close_overlay(self, event=None):
        """
        关闭置顶显示窗口
        
        Args:
            event: 事件对象
        """
        # 从_current_overlay中移除引用
        if ScreenshotOverlay._current_overlay == self:
            ScreenshotOverlay._current_overlay = None

        # 关闭提示窗口
        if hasattr(self, 'tip_window') and self.tip_window:
            self.tip_window.destroy()
            self.tip_window = None

        if self.root:
            self.root.destroy()
            self.root = None

    def show_tip(self, event=None):
        """
        显示提示窗口

        Args:
            event: 事件对象
        """
        if hasattr(self, 'tip_window'):
            self.tip_window.deiconify()
            self.move_tip(event)

    def hide_tip(self, event=None):
        """
        隐藏提示窗口

        Args:
            event: 事件对象
        """
        if hasattr(self, 'tip_window'):
            self.tip_window.withdraw()

    def move_tip(self, event=None):
        """
        移动提示窗口到鼠标位置旁边

        Args:
            event: 事件对象
        """
        if hasattr(self, 'tip_window') and event:
            # 获取鼠标在屏幕上的位置
            x = event.x_root + 10
            y = event.y_root + 10
            self.tip_window.geometry(f"+{x}+{y}")


def show_screenshot_overlay(image, position):
    """
    显示截图置顶窗口的便捷函数（非阻塞方式）
    
    Args:
        image (PIL.Image): 要显示的图像
        position (tuple): 显示位置 (left, top)
    """
    overlay = ScreenshotOverlay(image, position)
    overlay.show_overlay()
